﻿/* Template done by
 * 
 * Richard Clark
 * Project Hoshimi Lead Manager
 * Contact at ori@c2i.fr
 * 
*/

using System;
using System.Collections.Generic;
using System.Text;
using VG.Common;
using VG.Map;
using System.Drawing;

namespace Los_Borbotones
{
    public class myPlayer : VG.Common.Player
    {
        #region Initializations
        public myPlayer() { }
        public myPlayer(string name, int ID)
            : base(name, ID)
        {
            this.ChooseInjectionPointEvent += new VG.Common.ChooseInjectionPointEventHandler(myPlayer_ChooseInjectionPoint);
            this.WhatToDoNextEvent += new VG.Common.WhatToDoNextEventHandler(myPlayer_WhatToDoNext);
        }
        public override System.Drawing.Bitmap Flag
        {
            get { return Properties.Resources.rcFlag; }
        }
        #endregion

        public const int MAX_NEEDLES = 12;
        public const int MAX_COLLECTORS = 2;

        public enum WhatToDoNextAction
        {
            NothingToDo,
            MoveTo,
            Build,
            AutoDestroy,
            Idle,
            SendPointsToExplorer,
            MakeAttack,
            BuildProtection,

        }
        private WhatToDoNextAction m_WhatToDoNext = WhatToDoNextAction.BuildProtection;
        public WhatToDoNextAction AI_WhatToDoNext
        {
            get { return m_WhatToDoNext; }
            set { m_WhatToDoNext = value; }
        }

        private void UpdateInformations()
        {
            if (nextID >= MAX_NEEDLES)
                AI_WhatToDoNext = WhatToDoNextAction.Idle;               
        }


        private void AI_DoActions()
        {            
            switch (this.AI_WhatToDoNext)
            {
                case WhatToDoNextAction.NothingToDo:
                    this.AI_WhatToDoNext = WhatToDoNextAction.Build;
                    break;

                case WhatToDoNextAction.MoveTo:
                    Point p = Utils.getNearestPoint(this.AI.Location, this.AZNEntities);
                    this.AI.MoveTo(p);
                    this.AI_WhatToDoNext = WhatToDoNextAction.SendPointsToExplorer;
                    break;

                case WhatToDoNextAction.Build:
                    constructCicle();
                    break;

                case WhatToDoNextAction.BuildProtection:
                    buildGuards();
                    break;

                case WhatToDoNextAction.AutoDestroy:
                    this.AI.ForceAutoDestruction();
                    break;

                case WhatToDoNextAction.Idle:
                    //this.AI_WhatToDoNext = WhatToDoNextAction.NothingToDo;
                    break;

                // Indicar al explorer que puntos mirar.                
                case WhatToDoNextAction.SendPointsToExplorer:
                    // recorro los robots para encontrar el explorador.
                    foreach (NanoBot bot in this.NanoBots)
                    {
                        if (bot is Explorer && ((Explorer)bot).WhatToDoNext == Explorer.WhatToDoNextAction.WaitingForPoints)
                        {
                            this.LogText = "Enviando puntos al explorador\n";
                            SelectObjectivePoints((Explorer)bot);
                            ((Explorer)bot).WhatToDoNext = Explorer.WhatToDoNextAction.MoveToPoint;
                        }
                    }
                    // update state of IA.
                    this.AI_WhatToDoNext = WhatToDoNextAction.MakeAttack;
                    break;

                // Indica al explorer que puntos atacar.
                case WhatToDoNextAction.MakeAttack:
                    // recorro los robots para encontrar el explorador.
                    foreach (NanoBot bot in this.NanoBots)
                    {
                        if (bot is Protector && ((Protector)bot).WhatToDoNext == Protector.WhatToDoNextAction.WaitingForAttackPoints)
                        {
                            this.LogText = "Enviando puntos de ataque\n";
                            PassObjectivesAttackToProtector((Protector)bot);
                            //((Protector)bot).WhatToDoNext = Protector.WhatToDoNextAction.Attack;
                        }
                    }
                    // update state of IA.                       
                    this.AI_WhatToDoNext = WhatToDoNextAction.MakeAttack;
                    break;
                
            }
        }

        private void myPlayer_WhatToDoNext()
        {
            UpdateInformations();

            if (this.AI.State == NanoBotState.WaitingOrders)
                AI_DoActions();

            foreach (NanoBot bot in this.NanoBots)
                if (bot is IActionable)
                    ((IActionable)bot).DoActions();
        }

        #region Construction Steps
        private ConstStepAction consCicleStep = 0;
        private List<Entity> m_visitedEntities = new List<Entity>();

        //Lista de entidades visitadas (HoshimiPts)
        public List<Entity> VisitedEntities { get { return m_visitedEntities; } }

        public enum ConstStepAction
        {
            init = 0,
            buildingNeedle,
            buildingProtector,
            buildingColector,
            buildingExplorer,
            done,
        }
        private Entity HP_ent;

        //TODO: hacer una clase especial para guardar info de peloton
        private Dictionary<String, Group> m_groups = new Dictionary<string, Group>();
        public Dictionary<String, Group> Groups { get { return m_groups; } }

        private List<Group> m_ex_groups = new List<Group>();
        public List<Group> ExGroups { get { return m_ex_groups; } }


        private int nextID = 0;
        private int countColl = 1;
        private bool needleBuilded;

        private bool constructCicle()
        {
            switch (consCicleStep)
            {
                case ConstStepAction.init:
                    HP_ent = Utils.getNearestEntity(this.AI.Location, this.HoshimiEntities, this.VisitedEntities);
                    this.AI.MoveTo(new Point(HP_ent.X, HP_ent.Y));
                    consCicleStep++;            
                    break;
                case ConstStepAction.buildingNeedle:
                    this.VisitedEntities.Add(HP_ent);
                    needleBuilded = this.AI.Build(typeof(Needle), "" + nextID);
                    consCicleStep++;            
                    break;
                case ConstStepAction.buildingProtector:
                    this.Groups.Add("" + nextID, new Group("" + nextID, HP_ent));
                    this.AI.Build(typeof(Defender), "" + nextID);
                    consCicleStep++;            
                    break;
                case ConstStepAction.buildingColector:
                    this.AI.Build(typeof(Collector), "" + nextID);
                    if (countColl < MAX_COLLECTORS)
                        countColl++;
                    else
                        consCicleStep++;            
                    break;
                case ConstStepAction.buildingExplorer:
                    this.AI.Build(typeof(Radar), "" + nextID);
                    consCicleStep++;            
                    break;
                case ConstStepAction.done:
                    nextID++;
                    countColl = 1;
                    consCicleStep = ConstStepAction.init;
                    //this.AI_WhatToDoNext = WhatToDoNextAction.MoveTo;
                    break;
            }            
            return true;
        }
        #endregion

        #region Build Protection
        private int step = 0;
        private void buildGuards(){
            switch (step)
            {
                case 0:
                    this.AI.Build(typeof(Scout));
                    step++;
                    break;
                case 1:
                    this.AI.Build(typeof(Guard));
                    step++;
                    break;
                case 2:
                    this.AI.Build(typeof(Guard));
                    step++;
                    break;
                case 3:
                    this.AI.Build(typeof(Guard));
                    step++;
                    this.m_WhatToDoNext = WhatToDoNextAction.Build;
                    break;
            }
        }
        #endregion

        #region Injection Point
        private List<Entity> m_AznEntities = new List<Entity>();
        private List<Entity> m_HoshimiEntities = new List<Entity>();

        //Listas de AZN y HoshimiPoints
        public List<Entity> AZNEntities { get { return m_AznEntities; } }
        public List<Entity> HoshimiEntities { get { return m_HoshimiEntities; } }

        private void myPlayer_ChooseInjectionPoint()
        {
            //guardo AZN y Hoshimi Points
            foreach (Entity ent in this.Tissue.Entities)
            {
                switch (ent.EntityType)
                {
                    case EntityEnum.AZN:
                        AZNEntities.Add(ent);
                        break;
                    case EntityEnum.HoshimiPoint:
                        HoshimiEntities.Add(ent);
                        break;
                }
            }

            Point pier = this.PierreTeamInjectionPoint;
            Point ip = Utils.getFarPoint(pier, HoshimiEntities);
            Point near = Utils.getNearestPoint(pier, HoshimiEntities);
            Point[] pts = new Point[2];
            pts[0] = ip;
            pts[1] = near;
            Point res = Utils.getMiddlePoint(pts);
            //Entity e = Utils.getNearestEntity(ip, HoshimiEntities, null);
            //List<Entity> le = new List<Entity>();
            //le.Add(e);
            //Entity ie = Utils.getNearestEntity(ip, HoshimiEntities, le);
            Entity ie = Utils.getNearestEntity(res, HoshimiEntities, null);
            this.InjectionPointWanted = new Point(ie.X, ie.Y);
        }

        public void PassObjectivesAttackToProtector(Protector _prot)
        {
            foreach (NanoBotInfo info in this.OtherNanoBotsInfo)
            {
                if (BotOfPierreTeam(info.ID))
                {
                    _prot.PointsToAttack.Enqueue(new Point(info.Location.X, info.Location.Y));
                    _prot.WhatToDoNext = Protector.WhatToDoNextAction.GoingToPointOfAtack;
                }
            }
        }

        private void SelectObjectivePoints(Explorer explo)
        {
            //explo.PointsToVisit.Clear();
         //   for (int i = 0; i < 10; i++)
            {
                explo.PointsToVisit.Enqueue(new Point(this.AI.Location.X, this.AI.Location.Y));
            }
            explo.WhatToDoNext = Explorer.WhatToDoNextAction.MoveToPoint;
        }

        
        public Boolean BotOfPierreTeam(int _id)
        {
            return _id == 0;
        }



        #endregion

    }
}
